<template>
  <div class="app-container">

    <!-- 查询和其他操作 -->
    <div class="filter-container">
      <el-button class="filter-item" type="primary" icon="el-icon-plus" @click="handleCreate">{{ $t('product.controller.upsert.create') }}</el-button>
      <el-button class="filter-item" type="primary" icon="el-icon-camera" @click="handlerRender">{{ $t('product.controller.upsert.render') }}</el-button>
    </div>

    <!-- 表格区 -->
    <el-table
      ref="dragTable"
      v-loading="listLoading"
      :data="list"
      row-key="id"
      :element-loading-text="$t('product.controller.upsert.searching')"
      border
      fit
      highlight-current-row
      style="width: calc(100% - 450px)"
    >
      <el-table-column align="center" :label="$t('product.controller.upsert.id')" width="80" prop="id" />

      <el-table-column align="center" :label="$t('product.controller.upsert.componentId')" width="80" prop="componentLibId" />

      <el-table-column align="center" :label="$t('product.controller.upsert.componentTitle')" prop="componentTitle" />

      <el-table-column align="center" :label="$t('product.controller.upsert.title')" prop="title" />

      <el-table-column align="center" :label="$t('product.controller.upsert.operation')" width="250" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('product.controller.upsert.edit') }}</el-button>
          <el-button type="danger" style="margin:5px" size="mini" @click="handleDelete(scope.row)">{{ $t('product.controller.upsert.deletE') }}</el-button>
        </template>
      </el-table-column>

      <el-table-column align="center" :label="$t('product.controller.upsert.drag')" width="80">
        <template slot-scope="{}">
          <svg-icon class="drag-handler" icon-class="drag" />
        </template>
      </el-table-column>
    </el-table>

    <!-- 预览fixed区 -->
    <div class="demo-model">
      <div class="model-content">
        <iframe scrolling="auto" frameborder="0" :src="iframeSrc" class="iframe" />
      </div>
    </div>

    <!-- 抽屉 -->
    <el-drawer
      :title="upsertDrawerText"
      :visible.sync="upsertDrawerVisible"
      :before-close="handleDrawerClose"
      direction="ltr"
      custom-class="custom-drawer"
      @opened="onDrawerOpened"
    >
      <el-form ref="upsertForm" :model="upsertForm" label-width="80px" style="padding: 0px 10px">
        <el-form-item :label="$t('product.controller.upsert.chooseComponent')">
          <el-select
            v-model="upsertForm.componentLibId"
            :placeholder="$t('product.controller.upsert.chooseComponentPlaceholder')"
            :disabled="upsertDrawerText === $t('product.controller.upsert.componentEdit')"
            @change="loadComponentAttr"
          >
            <el-option v-for="(item,index) in componentLibraryList" :key="index" :label="item.title" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item :label="$t('product.controller.upsert.title')">
          <el-input ref="upsertForm_title" v-model="upsertForm.title" />
        </el-form-item>
        <!-- 布局样式 -->
        <div style="height: 15px" />
        <el-divider content-position="left">{{ $t('product.controller.upsert.styleAttr') }}</el-divider>
        <div style="margin-top: 20px" />
        <el-form-item>
          <el-radio-group v-model="upsertForm.styleMode" size="medium" @change="onStyleModeChange">
            <el-radio-button :label="1">{{ $t('product.controller.upsert.systemStyle') }}</el-radio-button>
            <el-radio-button :label="2">{{ $t('product.controller.upsert.customStyle') }}</el-radio-button>
          </el-radio-group>
        </el-form-item>

        <el-form-item v-if="upsertForm.styleMode === 1" :label="$t('product.controller.upsert.display')">
          <el-select v-model="upsertForm.display" :placeholder="$t('select.select')">
            <el-option label="none" value="none">none</el-option>
            <el-option label="inline" value="inline">inline</el-option>
            <el-option label="block" value="block">block</el-option>
            <el-option label="inline-block" value="inline-block">inline-block</el-option>
          </el-select>
        </el-form-item>

        <el-form-item v-if="upsertForm.styleMode === 1" :label="$t('product.controller.upsert.margin')">
          <el-input v-model="upsertForm.margin" />
        </el-form-item>

        <el-form-item v-if="upsertForm.styleMode === 1" :label="$t('product.controller.upsert.padding')">
          <el-input v-model="upsertForm.padding" />
        </el-form-item>

        <el-form-item v-if="upsertForm.styleMode === 1" :label="$t('product.controller.upsert.width')">
          <el-input v-model="upsertForm.width" />
        </el-form-item>

        <el-form-item v-if="upsertForm.styleMode === 1" :label="$t('product.controller.upsert.height')">
          <el-input v-model="upsertForm.height" />
        </el-form-item>

        <el-form-item v-if="upsertForm.styleMode === 2" :label="$t('product.controller.upsert.style')">
          <el-input
            v-model="upsertForm.style"
            type="textarea"
            :rows="4"
            :placeholder="$t('product.controller.upsert.styleplaceholder')"
          />
        </el-form-item>

        <!-- 动态渲染的属性 -->
        <div style="height: 15px" />
        <el-divider content-position="left">{{ $t('product.controller.upsert.componentAttr') }}</el-divider>
        <el-form-item v-for="(item, index) in componentLibraryAttrList" :key="index" :label="item.title">
          <el-select v-if="item.type === 5" v-model="valueList[index]" placeholder="请选择">
            <el-option
              v-for="option in item.enumas"
              :key="option"
              :label="option"
              :value="option"
            />
          </el-select>
          <el-input v-else v-model="valueList[index]" />
        </el-form-item>
        <!-- 动态渲染的属性END -->
        <div style="height: 15px" />
        <el-form-item>
          <el-button v-if="upsertDrawerText === $t('product.controller.upsert.componentCreate')" :loading="submitting" type="primary" @click="doCreate">{{ $t('product.controller.upsert.componentDoCreate') }}</el-button>
          <el-button v-else :loading="submitting" type="primary" @click="doUpdate">{{ $t('product.controller.upsert.componentDoEdit') }}</el-button>
          <el-button @click="upsertDrawerVisible = false">{{ $t('product.controller.upsert.componentClose') }}</el-button>
        </el-form-item>
      </el-form>
    </el-drawer>
  </div>
</template>

<script>
import Sortable from 'sortablejs'
import { listLibrary, listComponent, listLibraryAttr, createComponent, editComponent, listComponentAttr, adjustComponentSort, deleteComponent } from '@/api/controller'
export default {
  name: 'ControllerUpsert',
  data() {
    return {
      controllerId: undefined,
      listLoading: false,
      total: 2,
      list: [],
      // old 和 new 两个是拖动使用的中间对象
      oldList: [],
      newList: [],
      sortable: null,
      // 产品列表
      productList: [],
      iframeSrc: 'https://h5.uviewui.com',
      // 组件设置(面板)
      upsertDrawerText: '',
      upsertDrawerVisible: false,
      upsertDrawerSaved: false,
      upsertForm: {
        styleMode: 1,
        componentLibId: undefined,
        title: '',
        style: ''
      },
      // 当前选中组件属性列表
      componentLibraryAttrList: [],
      valueList: [],
      // 组件列表
      componentLibraryList: [],
      submitting: false
    }
  },
  created() {
    this.init()
    if (this.controllerId) {
      this.getList()
    }
  },
  methods: {
    init() {
      // 获取初始数据
      const cid = this.$route.query.controllerId
      if (cid) {
        this.controllerId = parseInt(cid)
      } else {
        this.$notify({
          title: this.$t('message.fail'),
          message: this.$t('product.controller.upsert.controllerIdEmpty'),
          type: 'error'
        })
        this.$router.go(-1)
        return
      }
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      listLibrary()
        .then(res => {
          this.componentLibraryList = res.data
          // 默认让其选中第一个
          if (this.componentLibraryList.length > 0) {
            this.upsertForm.componentLibId = this.componentLibraryList[0].id
          }
          loading.close()
          this.getList()
        })
        .catch(failres => {
          this.$notify({
            title: this.$t('message.fail'),
            message: this.$t('product.controller.upsert.listLibraryFail'),
            type: 'error'
          })
          loading.close()
        })
    },
    getList() {
      this.listLoading = true
      listComponent(this.controllerId)
        .then(res => {
          this.list = res.data
          this.listLoading = false
          this.oldList = this.list.map(v => v.id)
          this.newList = this.oldList.slice()
          this.$nextTick(() => {
            this.setSort()
            this.handlerRender()
          })
        })
        .catch(failres => {
          this.listLoading = false
        })
    },
    // 更新
    handleUpdate(row) {
      // 1.获取回显属性
      const styleObj = {}
      if (row.styleMode === 1) {
        // 将style解析
        if (row.style) {
          const styles = row.style.split(';')
          for (let i = 0; i < styles.length; i++) {
            const style = styles[i].trim()
            if (style) {
              const temp = style.split(':')
              styleObj[temp[0]] = temp[1]
            }
          }
        }

        // 补全空值
        if (!styleObj.margin) {
          styleObj.margin = ''
        }
        if (!styleObj.padding) {
          styleObj.padding = ''
        }
        if (!styleObj.height) {
          styleObj.height = ''
        }
        if (!styleObj.width) {
          styleObj.width = ''
        }
        if (!styleObj.display) {
          styleObj.display = ''
        }
      }
      this.upsertForm = {
        id: row.id,
        styleMode: row.styleMode,
        componentLibId: row.componentLibId,
        title: row.title,
        style: row.style,
        ...styleObj
      }
      // 过度加载
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      listComponentAttr(row.id)
        .then(res => {
          this.loadComponentAttr(res.data, () => {
            // 加载成功，显示面板
            this.upsertDrawerVisible = true
            this.upsertDrawerSaved = false
            this.upsertDrawerText = this.$t('product.controller.upsert.componentEdit')
            loading.close()
          }, () => {
            loading.close()
          })
        })
    },
    // 增加
    handleCreate() {
      // 1. 检测组件库是否成功获取
      if (this.componentLibraryList.length === 0) {
        this.$notify({
          title: this.$t('message.fail'),
          message: this.$t('product.controller.upsert.listLibraryFail')
        })
        return
      }
      // 重置表单
      this.upsertForm = {
        componentLibId: this.componentLibraryList[0].id,
        styleMode: 1,
        title: '',
        style: ''
      }
      // 过度加载
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      // 加载属性
      this.loadComponentAttr([], () => {
        // 加载成功，显示面板
        this.upsertDrawerVisible = true
        this.upsertDrawerSaved = false
        this.upsertDrawerText = this.$t('product.controller.upsert.componentCreate')
        loading.close()
      }, () => {
        loading.close()
      })
    },
    // 更新 & 增加 加载组件特殊属性
    loadComponentAttr(echoAttrList, success, fail) {
      listLibraryAttr(this.upsertForm.componentLibId)
        .then(res => {
          this.valueList = []
          this.componentLibraryAttrList = res.data
          // 要根据这个表，和已有属性进行回显
          // 将这个表进行扩展，将value值放进去
          this.componentLibraryAttrList.forEach(item => {
            // 增加则放入空值
            let value = ''
            if (echoAttrList.length !== 0) {
              // 根据已有属性表，将value回显
              for (let i = 0; i < echoAttrList.length; i++) {
                if (echoAttrList[i].componentLibAttrId === item.id) {
                  value = echoAttrList[i].value
                }
              }
            }
            // 每次循环必须执行到这里
            this.valueList.push(value)
            // 展开枚举
            if (item.type === 5) {
              item.enumas = JSON.parse(item.enumas)
            }
          })
          if (success) {
            success()
          }
        }).catch(failres => {
          if (fail) {
            fail()
          }
        })
    },
    // 删除
    handleDelete(row) {
      this.$confirm('您确定要删除组件"' + row.title + '"吗?此过程不可逆,是否继续', '提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消'
      }).then(res => {
        deleteComponent(row.id)
          .then(res => {
            this.$notify.success({
              title: '成功',
              message: '删除成功!'
            })
            this.getList()
            this.handlerRender()
          })
      })
    },
    doUpdate() {
      const attrList = this.buildFormAttrs()
      const form = {
        styleMode: this.upsertForm.styleMode,
        componentId: this.upsertForm.id,
        title: this.upsertForm.title,
        // 内部有JSON格式化
        attrList: attrList,
        style: this.upsertForm.style
      }
      if (form.styleMode === 1) {
        form.style = this.getStyleString()
      }
      this.submitting = true
      editComponent(form)
        .then(res => {
          // 创建组件成功，
          this.$notify({
            title: this.$t('message.success'),
            message: this.$t('product.controller.upsert.editCompenentSuccess'),
            type: 'success'
          })
          this.submitting = false
          this.upsertDrawerSaved = true
          this.upsertDrawerVisible = false
          this.getList()
          this.handlerRender()
        }).catch(failres => {
          this.submitting = false
        })
    },
    doCreate() {
      const attrList = this.buildFormAttrs()
      const form = {
        styleMode: this.upsertForm.styleMode,
        controllerId: this.controllerId,
        componentLibId: this.upsertForm.componentLibId,
        title: this.upsertForm.title,
        sort: this.list.length,
        // 内部有JSON格式化
        attrList: attrList
      }
      if (form.styleMode === 1) {
        form.style = this.getStyleString()
      }
      this.submitting = true
      createComponent(form)
        .then(res => {
          // 创建组件成功，
          this.$notify({
            title: this.$t('message.success'),
            message: this.$t('product.controller.upsert.createCompenentSuccess'),
            type: 'success'
          })
          this.submitting = false
          this.upsertDrawerSaved = true
          this.upsertDrawerVisible = false
          this.getList()
          this.handlerRender()
        }).catch(failres => {
          this.submitting = false
        })
    },
    buildFormAttrs() {
      const attrList = []
      for (let i = 0; i < this.valueList.length; i++) {
        // 若存在值，则将构建一个attr对象
        attrList.push({
          libAttrId: this.componentLibraryAttrList[i].id,
          value: this.valueList[i] ? this.valueList[i] : ''
        })
      }
      return attrList
    },
    // 抽屉关闭前回调，用于询问未保存是否保存
    handleDrawerClose(done) {
      if (!this.upsertDrawerSaved) {
        this.$confirm(this.$t('product.controller.upsert.upsertDrawerNotSaved'))
          .then(_ => {
            done()
          })
          .catch(_ => {})
      }
    },
    // 渲染
    handlerRender() {
      this.iframeSrc = 'http://localhost:8080/h5/pages/render/index' + '?id=' + this.controllerId + '&t=' + (new Date().getTime())
      console.log(this.iframeSrc)
    },
    setSort() {
      const el = this.$refs.dragTable.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
      this.sortable = Sortable.create(el, {
        ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
        setData: function(dataTransfer) {
          // to avoid Firefox bug
          // Detail see : https://github.com/RubaXa/Sortable/issues/1012
          dataTransfer.setData('Text', '')
        },
        onEnd: evt => {
          const targetRow = this.list.splice(evt.oldIndex, 1)[0]
          this.list.splice(evt.newIndex, 0, targetRow)

          // for show the changes, you can delete in you code
          const tempIndex = this.newList.splice(evt.oldIndex, 1)[0]
          this.newList.splice(evt.newIndex, 0, tempIndex)
          this.onChangeSort()
        }
      })
    },
    onDrawerOpened() {
      this.$refs.upsertForm_title.focus()
    },
    onChangeSort() {
      // 设置列表
      const map = {}
      for (let i = 0; i < this.list.length; i++) {
        map[this.list[i].id + ''] = i
      }
      adjustComponentSort(map)
        .then(res => {
          console.log('adjustOk')
        })
    },
    onStyleModeChange(e) {
      if (e === 2) {
        // 从预设模式切换到代码模式
        this.upsertForm.style = this.getStyleString()
      } else {
        // 从代码模式切换到预设模式
        if (this.upsertForm.style) {
          // 将style解析
          const styleObj = {}
          if (this.upsertForm.style) {
            const styles = this.upsertForm.style.split(';')
            for (let i = 0; i < styles.length; i++) {
              const style = styles[i].trim()
              if (style) {
                const temp = style.split(':')
                styleObj[temp[0]] = temp[1]
              }
            }
          }
          // 补全空值
          if (!styleObj.margin) {
            styleObj.margin = ''
          }
          this.upsertForm.margin = styleObj.margin
          if (!styleObj.padding) {
            styleObj.padding = ''
          }
          this.upsertForm.padding = styleObj.padding
          if (!styleObj.height) {
            styleObj.height = ''
          }
          this.upsertForm.height = styleObj.height
          if (!styleObj.width) {
            styleObj.width = ''
          }
          this.upsertForm.width = styleObj.width
          if (!styleObj.display) {
            styleObj.display = ''
          }
          this.upsertForm.display = styleObj.display
        }
      }
      this.$forceUpdate()
    },
    getStyleString() {
      let style = ''
      if (this.upsertForm.margin) {
        style += 'margin:' + this.upsertForm.margin + ';'
      }
      if (this.upsertForm.padding) {
        style += 'padding:' + this.upsertForm.padding + ';'
      }
      if (this.upsertForm.width) {
        style += 'width:' + this.upsertForm.width + ';'
      }
      if (this.upsertForm.height) {
        style += 'height:' + this.upsertForm.height + ';'
      }
      if (this.upsertForm.display) {
        style += 'display:' + this.upsertForm.display + ';'
      }
      return style
    }

  }
}
</script>

<style >
  .demo-model {
    box-sizing: border-box;
    overflow-y: auto;
    background-image: url(https://iotechn.oss-cn-hangzhou.aliyuncs.com/assets/iphonex-modal.png);
    background-repeat: no-repeat;
    background-size: 100%;
    box-shadow: 0 4px 25px 0 rgba(4,40,60,.18);
    border-radius: 30px;
    padding: 50px 10px 14px;
    position: fixed;
    z-index: 10;
    margin: 0;
    font-size: 16px;
    background-color: #fff;
    width: 310px;
    height: 680px;
    top: calc((100vh - 680px - 3.6rem)/2 + 3.6rem);
    right: 100px;
    display: block;
  }

  .model-content {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    border-bottom-left-radius: 30px;
    font-size: 16px;
  }

  .iframe {
    height: 100%;
    width: 100%;
    border-radius: 15px;
    font-size: 16px;
  }

  .sortable-ghost{
    opacity: .8;
    color: #fff!important;
    background: #42b983!important;
  }

  .custom-drawer {
    overflow: auto;
  }

</style>
